﻿using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using UtfUnknown;

namespace DevelopTool.Common
{
    /// <summary>
    /// 文件帮助类
    /// </summary>
    public static class FileHelper
    {

        #region 文件读写

        /// <summary>
        /// 读取文件，可指定读取编码，默认自动获取文件编码
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string ReadFile(string filePath, Encoding encoding = null)
        {
            if (encoding == null) encoding = GetFileEncoding(filePath);
            using (StreamReader reader = new StreamReader(filePath, encoding))
            {
                return reader.ReadToEnd();
            }
        }


        /// <summary>
        /// 写入文件，可设置写入编码，默认UTF8。如果文件已存在会覆盖
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="content"></param>
        /// <param name="encoding"></param>
        public static void WriteFile(string filePath, string content, Encoding encoding = null)
        {
            if (encoding == null) encoding = Encoding.UTF8;
            Directory.CreateDirectory(System.IO.Path.GetDirectoryName(filePath));
            using (StreamWriter writer = new StreamWriter(filePath, append: false, encoding))
            {
                writer.Write(content);
            }
        }

        #endregion 文件读写        


        #region 文件编码

        /// <summary>
        /// 获取文件的Encoding
        /// </summary>
        public static Encoding GetFileEncoding(string filePath)
        {
            DetectionResult result = CharsetDetector.DetectFromFile(filePath);
            if (result == null) return Encoding.UTF8;
            if (result.Detected == null) return Encoding.UTF8;
            return result.Detected.Encoding;
        }


        /// <summary>
        /// 获取文件的Encoding
        /// </summary>
        /// <param name="fileInfo"></param>
        /// <returns></returns>
        public static Encoding GetFileEncoding(this FileInfo fileInfo)
        {
            return GetFileEncoding(fileInfo.FullName);
        }

        #endregion 文件编码


        /// <summary>
        /// 打开CMD，并运行命令
        /// </summary>
        /// <param name="arguments"></param>
        public static void OpenRunCmd(string arguments)
        {
            if (string.IsNullOrEmpty(arguments)) return;

            ProcessStartInfo startInfo = new ProcessStartInfo
            {
                FileName = "cmd.exe", // 指定要运行的程序  
                Arguments = $"/K echo {GlobalData.AppName_zh}调用命令:{arguments} && " + arguments // /K 参数会在执行完命令后保持cmd窗口打开  
            };
            Process.Start(startInfo);
        }

        #region  调用系统文件属性显示窗口

        private const int SW_SHOW = 5;
        private const uint SEE_MASK_INVOKEIDLIST = 12;

        [DllImport("shell32.dll")]
        static extern bool ShellExecuteEx(ref SHELLEXECUTEINFO lpExecInfo);
        [StructLayout(LayoutKind.Sequential)]
        private struct SHELLEXECUTEINFO
        {
            public int cbSize;
            public uint fMask;
            public IntPtr hwnd;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpVerb;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpFile;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpParameters;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpDirectory;
            public int nShow;
            public IntPtr hInstApp;
            public IntPtr lpIDList;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpClass;
            public IntPtr hkeyClass;
            public uint dwHotKey;
            public IntPtr hIcon;
            public IntPtr hProcess;
        }

        /// <summary>
        /// 调用系统文件属性显示窗口
        /// </summary>
        /// <param name="Filename"></param>
        public static void ShowFileProperties(string filePath)
        {
            SHELLEXECUTEINFO info = new SHELLEXECUTEINFO();
            info.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(info);
            info.lpVerb = "properties";
            info.lpFile = filePath;
            info.nShow = SW_SHOW;
            info.fMask = SEE_MASK_INVOKEIDLIST;
            ShellExecuteEx(ref info);
        }

        #endregion  调用系统文件属性显示窗口

        /// <summary>
        /// 检查文件是否存在，并在文件已存在时生成带有递增序号（如(1)、(2)、(3)等）的新文件名
        /// </summary>
        /// <param name="baseFileName"></param>
        /// <param name="directoryPath"></param>
        /// <returns></returns>
        public static string GenerateUniqueFileName(string baseFileName, string directoryPath)
        {
            string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(baseFileName);
            string extension = Path.GetExtension(baseFileName);

            // 检查基础文件名（不带序号）的文件是否存在  
            string baseFilePath = Path.Combine(directoryPath, baseFileName);
            if (!File.Exists(baseFilePath))
            {
                // 如果不存在，直接返回基础文件名  
                return baseFileName;
            }

            // 使用正则表达式来查找文件名中已存在的最大序号  
            var regex = new Regex(@"\((\d+)\)$");
            int maxIndex = 0;

            foreach (var file in Directory.GetFiles(directoryPath, fileNameWithoutExtension + "*" + extension))
            {
                var match = regex.Match(Path.GetFileNameWithoutExtension(file));
                if (match.Success && int.TryParse(match.Groups[1].Value, out int index))
                {
                    maxIndex = Math.Max(maxIndex, index);
                }
            }

            // 生成新的文件名（带有递增序号）  
            string newFileName = $"{fileNameWithoutExtension}({maxIndex + 1}){extension}";

            // 理论上，由于我们已经检查了基础文件名，所以这里不需要再检查新文件名是否冲突  
            // 但为了安全起见（比如其他进程同时创建了同名文件），可以保留这部分逻辑  
            // while (File.Exists(Path.Combine(directoryPath, newFileName)))  
            // {  
            //     maxIndex++;  
            //     newFileName = $"{fileNameWithoutExtension}({maxIndex}){extension}";  
            // }  

            return newFileName;
        }

        /// <summary>
        /// 用本工具打开文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        public static void LocalOpenFile(string filePath)
        {
            Process.Start(GlobalData.AppPath, "\"" + filePath + "\"" + " Action=OpenFile");
        }

        /// <summary>
        /// 尝试删除文件
        /// </summary>
        /// <param name="fi">文件名</param>
        /// <returns>结果</returns>
        public static bool TryDelete(this FileInfo fi)
        {
            try
            {
                File.Delete(fi.FullName);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
        }
    }

}
